package com.yueyang.sojourn.server.common.baymax.web.filter;

import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Base64;
import java.util.Enumeration;

/**
 * 自动暴露实例的标识，方便排查问题
 * 
 * @author huisman
 * @Copyright (c) 2015, yueyang Group All Rights Reserved.
 */
public class InstanceHeaderExposeFilter implements Filter {
  private InstanceHeader instanceHeader = new InstanceHeader();
  private String instanceHeaderName = "X-Instance-Id";

  public InstanceHeaderExposeFilter() {}

  public InstanceHeaderExposeFilter(String instanceHeaderName) {
    if (StringUtils.hasText(instanceHeaderName)) {
      this.instanceHeaderName = instanceHeaderName;
    }
  }


  @Override
  public void init(FilterConfig filterConfig) throws ServletException {}

  @Override
  public void doFilter(ServletRequest request, ServletResponse sresponse, FilterChain chain)
      throws IOException, ServletException {
    // 首先所有请求添加 StandardHttpHeaders#X_Instance_Id header
    HttpServletResponse response = (HttpServletResponse) sresponse;
    // 只是追加header，如果已存在，同一个name 会有多个值。
    response.addHeader(instanceHeaderName, instanceHeader.getInstanceId());
    chain.doFilter(request, response);
  }

  @Override
  public void destroy() {}

  /**
   * 实例请求头,用于定位响应请求的服务器
   */
  public static class InstanceHeader {
    /**
     * DES密钥 - instanceId可以解密到对应节点的IP
     */
    private static final String SECRET_KEY = "a18ed2e4fdfd45f96ce83a5edc2f7f965";
    private String ip;
    private String instanceId;

    public InstanceHeader() {
      this.ip = findFirstNonLoopbackAddress();
      this.instanceId = Base64.getUrlEncoder().encodeToString(com.yueyang.sojourn.server.common.baymax.web.filter.DES.encrypt(this.ip, SECRET_KEY));
    }

    private String findFirstNonLoopbackAddress() {
      InetAddress result = null;
      try {
        int lowest = Integer.MAX_VALUE;
        for (Enumeration<NetworkInterface> nics =
            NetworkInterface.getNetworkInterfaces(); nics.hasMoreElements();) {
          NetworkInterface ifc = nics.nextElement();
          if (ifc.isUp()) {
            if (ifc.getIndex() < lowest || result == null) {
              lowest = ifc.getIndex();
            } else if (result != null) {
              continue;
            }

            for (Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs
                .hasMoreElements();) {
              InetAddress address = addrs.nextElement();
              if (address instanceof Inet4Address && !address.isLoopbackAddress()) {
                result = address;
              }
            }
          }
        }
      } catch (IOException ex) {}
      if (result != null) {
        return result.getHostAddress();
      }

      try {
        return InetAddress.getLocalHost().getHostAddress();
      } catch (UnknownHostException e) {}
      return "Unknown";
    }



    /**
     * 服务器IP
     */
    public String getIp() {
      return ip;
    }

    /**
     * 实例ID
     */
    public String getInstanceId() {
      return instanceId;
    }

    @Override
    public String toString() {
      return "InstanceHeader [ip=" + ip + ", instanceId=" + instanceId + "]";
    }

    /**
     * 解析实例对应的服务器IP
     * 
     * @param instanceId
     */
    public static String resolveInstanceId(String instanceId) {
      return new String(
          com.yueyang.sojourn.server.common.baymax.web.filter.DES.decrypt(Base64.getUrlDecoder().decode(instanceId), SECRET_KEY.getBytes()));
    }
  }
}
